#!/usr/bin/env python
################################################################################
#
#   svg_from_domains
# 
#
#
#   Copyright (C) 2007 Leo Goodstadt
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public License
#   as published by the Free Software Foundation; version 2
#   of the License
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#################################################################################
"""
    svg_from_domains.py

"""

import sys, os
import os.path
import re
import StringIO
import glob
import shutil
# add self to search path for testing
if __name__ == '__main__':
    exe_path = os.path.split(os.path.abspath(sys.argv[0]))[0]
    sys.path.append(exe_path)

# get module name
if __name__ == '__main__':
    myname = os.path.splitext(os.path.split(sys.argv[0])[1])[0];
else:
    myname = __name__

from SVGdraw import *
import SVGdraw


#
#   parse domains from either open file or file like iterator over lines
# 
#       first line should be beg / end of peptide
#       other lines should be beg<tab>end<tab>domain_name
# 
#       
# 
# 
def parse_domains_data(file):
    """
        parse domains from either open file or file like iterator over lines
        
           first line should be [beg, end) of peptide
           other lines should be beg<tab>end<tab>domain_name
                where [beg,end) = domain coordinates
    """
    domains = dict()

    lines = iter(file)

    # first line contains bounds
    firstline = lines.next()
    peptide_beg, peptide_end =  map(int, firstline.split("\t",2))

    domain_names = list()
    unique_domain_names = dict()
    
    for line_cnt, line in enumerate(lines):

        # skip blank lines
        line = line.rstrip()
        if not len(line):
            continue;
        try:
            domain_beg, domain_end, domain_name =  line.split("\t", 3)
        except :
            sys.stderr.write("three fields expected at line # %d \n(%s)" %
                                (line_cnt + 2, line))
            sys.exit(1)
        domain_beg, domain_end = map(int, [domain_beg, domain_end])
        domains.setdefault(domain_name, []).append([domain_beg, domain_end])

        #
        #   add to list of domain names
        # 
        if domain_name in unique_domain_names:
            continue
        domain_names.append(domain_name)
        unique_domain_names[domain_name] = 1

        
    return [domains, domain_names, peptide_beg, peptide_end]







    

from plot_scaling import plot_scaling 

def plot_domains_from_file (scaling, domains_data_file, domain_bounds, draw_properties):
    domains_data = parse_domains_data(domains_data_file)

    return plot_domains (scaling, domains_data, domain_bounds, draw_properties)

from svg_draw_properties import svg_draw_properties
    
def plot_domains (scaling, domains_data, domain_bounds, draw_properties = dict()):
    """
        draws "wobbly line stringing together exons.
            with wobbly_pos = y coordinate of the extent of the wobbly line
            with straight_pos = y coordinate of the exonic (straight part)
          if wobbly_pos < straight_pos, the line will be drawn pointing down
            
        exon_dimensions is a list of the op and bottom of the exon rectangles

        scaling is a type of plot_scaling

        transcripts is a dictionary of begin and ends
    """

    # resulting svg elements
    svg_elements = dict()
    
    # parse out domains_data
    domains, domain_names, peptide_beg, peptide_end = domains_data



    # 
    #   line is black
    # 
    if 'line' not in draw_properties:
        draw_properties['line'] = svg_draw_properties()
        draw_properties['line'].outline_width = \
                                    scaling.y_scale(draw_properties['line'].outline_width)
        
    #
    #   set domains to sucessive colours
    # 
    colours = ['red', 'green', 'blue', 'black', 'antiquewhite', 
               'maroon', 'mediumspringgreen', 'mediumslateblue']
    for colour_index, domain_name in enumerate(domain_names):
        if domain_name not in draw_properties:
            draw_properties[domain_name] = svg_draw_properties()
            draw_properties[domain_name].fill = colours[colour_index % len(colours)]
            draw_properties[domain_name].stroke = "none"


            
    domain_top = scaling.to_y(domain_bounds[0])
    domain_bot = scaling.to_y(domain_bounds[1])
    domain_mid = (domain_top + domain_bot) / 2

    
    # domain line
    svg_elements['line'] = line(scaling.to_x(peptide_beg), domain_mid, 
                               scaling.to_x(peptide_end), domain_mid,
                                **draw_properties['line']())



    svg_elements['domains'] = list()
    for domain_name in domain_names:
        svg_elements['domains'].append(group(domain_name))
        for beg, end in domains[domain_name]:
            svg_elements['domains'][-1].addElement(
                rect(scaling.to_x(beg),
                         domain_bot, 
                         (end - beg) * scaling.x_scale, 
                         domain_top - domain_bot, 
                         **draw_properties[domain_name]()))
            

    
    return svg_elements

if __name__ == '__main__':
    test_data = \
"""0	3152
680	721	EGF_Ca
732	770	EGF_Ca
770	808	EGF_Ca
808	848	EGF_Ca
927	965	EGF_Ca
1160	1198	EGF_Ca
1003	1041	EGF_Ca
1041	1078	EGF_Ca
215	255	EGF
892	927	EGF
968	1003	EGF
1081	1116	EGF
1119	1160	EGF
172	213	EGF
258	293	EGF
318	369	EGF
372	407	EGF
552	603	EGF
638	680	EGF_Dead
851	889	EGF
1200	1238	EGF
2101	2141	EGF
2337	2372	EGF
2373	2409	EGF
2612	2647	EGF
2650	2690	EGF
2877	2912	EGF
2914	2950	EGF
0	21	signalpeptide
1337	1351	lowcomplexity
1638	1653	lowcomplexity
1902	2046	LamG
2170	2317	LamG
2439	2585	LamG
2715	2856	LamG
2977	3120	LamG
"""
    test_data = test_data.split("\n")
    # 
    # create drawing then you create a SVG root element
    # 
    drawing=drawing()
    svg_root=svg()

    sys.stderr.write("plot domains...\n")
    
    # in mm
    paper_width  = 297
    paper_height = 210
    paper_margin = 20
    peptide_end = 3152
    peptide_beg = 0
    domain_extent = peptide_end - peptide_beg
    internal_width  = paper_width - paper_margin * 2
    internal_height = paper_height - paper_margin * 2


    # svg root discription
    svg_root.attributes["width"]    = str(paper_width) + "mm"
    svg_root.attributes["height"]   = str(paper_height) + "mm"
    svg_root.attributes["viewBox"] = "0 0 %d %d" % (paper_width, paper_height)
    transform_group = group("root transform")
    transform_group.attributes["transform"] = "translate(%d,%d)" % (0, paper_height)
    svg_root.addElement(transform_group)

    #
    # scaling factor
    # 
    domain_scaling = plot_scaling(float(internal_width)/domain_extent, float(-20), 
                                  paper_margin, -paper_margin, 
                                    peptide_beg, 0 )


    #
    # colour of lines
    # 
    draw_properties = dict()
    draw_properties['line'] = svg_draw_properties(stroke = 'red', 
                                                        stroke_width = 0.2)
    svg_elements = plot_domains_from_file  (domain_scaling, test_data, 
                                                    [0.0, 1.0],
                                                    draw_properties)


    #
    # add domains to svg root
    # 
    transform_group.addElement(svg_elements['line'])
    for d in svg_elements['domains']:
        transform_group.addElement(d)
    
    drawing.setSVG(svg_root)
    print drawing.toXml()
    sys.stderr.write("Done...\n")

